﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the GNU General Public License version 2 (GPLv2).
// See accompanying file License.txt or copy at http://phuse.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Phuse.Net
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Text;

    /// <summary>Represents the base of all multiline responses where an object of the type representing a single line
    /// of the response can be created by passing one argument.</summary>
    /// <typeparam name="TMostDerived">The most-derived subclass of this type.</typeparam>
    /// <typeparam name="TResponseLine">The type that exposes the data that is parsed from a single line of the
    /// response.</typeparam>
    /// <typeparam name="TP1">The type of the parameter needed to create a <typeparamref name="TResponseLine"/>
    /// object, see remarks.</typeparam>
    /// <remarks>
    /// <para><typeparamref name="TP1"/> corresponds to the type of the 1st word of each line.</para>
    /// <para>The type represented by <typeparamref name="TP1"/> must either be a string or expose a method with the
    /// following signature:
    /// <code>public static TP Parse(string s, IFormatProvider provider)</code>
    /// where <c>TP</c> is equal to the type exposing the Parse method.</para>
    /// <para>Concrete responses never derive directly from this class, but subclass protocol-specific variants, like
    /// e.g. <see cref="Nntp.MultilineResponse{T, U, V}"/>.</para>
    /// </remarks>
    /// <threadsafety static="true" instance="false"/>
    [SuppressMessage("Microsoft.Design", "CA1005:AvoidExcessiveParametersOnGenericTypes", Justification = "We absolutely need more than two type parameters.")]
    public abstract class MultilineResponseBase<TMostDerived, TResponseLine, TP1> :
        MultilineResponseBase<TMostDerived, TResponseLine>
        where TMostDerived : MultilineResponseBase<TMostDerived, TResponseLine, TP1>
    {
        internal MultilineResponseBase(Stream subsequentLines, Encoding encoding) :
            base(subsequentLines, encoding, 1, true, true)
        {
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>When overridden in a derived class constructs a <typeparamref name="TResponseLine"/> object
        /// from the argument passed for <paramref name="p1"/> and returns the <typeparamref name="TResponseLine"/>
        /// object.</summary>
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "These are generic parameter names.")]
        protected abstract TResponseLine CreateResponseLine(TP1 p1);

        /// <summary>See <see cref="MultilineResponseBase{TMostDerived, TResponseLine}.CreateResponseLine"/>.</summary>
        /// <exception cref="InvalidOperationException"><typeparamref name="TP1"/> does not offer a Parse method with
        /// required signature, see class remarks.</exception>
        /// <remarks>Parses the string at index 0 of <paramref name="responseLineWords"/> with the Parse method of
        /// the type represented by <typeparamref name="TP1"/>. Then calls
        /// <see cref="MultilineResponseBase{T, U, V}.CreateResponseLine(V)"/> with the result as argument and returns
        /// the new result.</remarks>
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Method is not supposed to be called by external code.")]
        protected sealed override TResponseLine CreateResponseLine(ArraySegment<byte>[] responseLineWords)
        {
            return this.CreateResponseLine(Parser<TP1>.Parse(responseLineWords[0], this.Encoding));
        }
    }
}
